import java.sql.Connection;

import javax.swing.SwingUtilities;

import swing.AutomaticTellerService;

public class MBank {

	private static MBank instance = null;
	private Connection conn = null;
	private AccountDBManager accountDBManager;
	private CustomerDBManager customerDBManager;
	private DepositDBManager depositDBManager;
	private PropertyDBManager propertyDBManager;
	private RankDBManager rankDBManager;
	private DepositTypesDBManager depositTypesDBManager;
	private ClientReports clientReports;
	private AdminReports adminReports;
	private GeneralReports generalReports;
	private BalanceDBManager balanceDBManager;
	private DepositCheckThread depositCheckThread;
	private IndexUpdateThread indexUpdateThread;

	private MBank() throws DBManagerException {

		// establish connection to database MBankDB
		conn = ConnectionDB.getConnectonData();
		System.out.println("[Mbank]: Connection to DB Esteblished.");

		propertyDBManager = new PropertyDBManager(conn);
		depositTypesDBManager = new DepositTypesDBManager(conn);
		rankDBManager = new RankDBManager(conn);
		balanceDBManager = new BalanceDBManager(conn, propertyDBManager);
		customerDBManager = new CustomerDBManager(conn, propertyDBManager, rankDBManager);
		accountDBManager = new AccountDBManager(conn, propertyDBManager, rankDBManager, balanceDBManager);
		depositDBManager = new DepositDBManager(conn, propertyDBManager, depositTypesDBManager, balanceDBManager, accountDBManager);
		generalReports = new GeneralReports(conn, depositDBManager, customerDBManager, accountDBManager, balanceDBManager, depositTypesDBManager);
		adminReports = new AdminReports(conn, depositDBManager, customerDBManager, accountDBManager, balanceDBManager, depositTypesDBManager);
		clientReports = new ClientReports(conn, depositDBManager, customerDBManager, accountDBManager, balanceDBManager, depositTypesDBManager);

		// check Rank DB Manager can get data from DB
		// and show it on the screen
		// rankDBManager.printRankTypes();
		// System.out.println("Credit is "
		// +rankDBManager.getCreditByMoneyAmount(1500));
		// System.out.println("Rank is "
		// +rankDBManager.getRankByMoneyAmount(124000));

		// threads = new Threads(conn, depositDBManager, depositTypesDBManager);
		// threads.DepositCheckThreadsNew();

		// define and activate CheckDepositThread
		// run 1 time a day and check if deposits time is over
		// call to Delete deposit function
		depositCheckThread = new DepositCheckThread(conn, depositDBManager);

		// new Thread(depositCheckThread).start();

		new Thread(depositCheckThread).start();

		// define and activate IndexUpdateThread
		// run 1 time a month - update interets rate for Deposits
		// and call to function Recalc Deposit
		indexUpdateThread = new IndexUpdateThread(conn, depositDBManager, depositTypesDBManager);
		System.out.println("[Mbank]: DB Managers Created.");
		System.out.println("[Mbank]: Mbank Created.");
	};

	// Singleton
	public static MBank getInstance() throws DBManagerException {

		if (instance == null) {
			instance = new MBank();
		}

		return instance;

	}

	public AdminActions adminLogin(String password) {
		return AccessManager.adminLogin(accountDBManager, customerDBManager, propertyDBManager, rankDBManager, generalReports, adminReports, depositTypesDBManager, balanceDBManager, depositDBManager, password);
	}

	public ClientActions clientLogin(long userId, long password) {
		return AccessManager.clientLogin(accountDBManager, customerDBManager, propertyDBManager, depositDBManager, depositTypesDBManager, balanceDBManager, conn, clientReports, userId, password);
	}

	public void closeConnection() {
		propertyDBManager.saveProperies();

		// add sleep before close connection for 4 sec for test thread
		// try {
		// Thread.sleep(3000); // sleep 1 day == 3 sec for our test
		// } catch (Exception e) {
		// // TODO: handle exception
		// }
		//
		// depositCheckThread.stopRunning(); // stop thread running
		//
		// indexUpdateThread.stopRunning(); // stop thread running

		// add sleep before close connection for 4 sec for test thread
		try {
			Thread.sleep(2000); // sleep 1 day == 3 sec for our test
		} catch (Exception e) {
			// TODO: handle exception
		}

		depositCheckThread.stopRunning(); // stop depositCheckThread

		indexUpdateThread.stopRunning(); // stop indexUpdateThread

		ConnectionDB.closeConnectionDataBase(conn);
		System.out.println("[Mbank]: Connection closed successfully.");
	}

	public void runSwing() {

		// It need to install Swing

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {

				new AutomaticTellerService();

			}
		});

	}
}
